package com.zgis.monitor.service.impl;

import com.zgis.monitor.config.MonitorConfig;
import com.zgis.monitor.model.ServiceStatus;
import com.zgis.monitor.model.dto.ServiceListDTO;
import com.zgis.monitor.service.MonitorService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

/**
 * 通孔服务统一管理
 */
@Service
@Primary
public class CompositeMonitorService implements MonitorService
{
    @Autowired
    private  JarMonitorService    jarMonitorService;
    @Autowired
    private  DockerMonitorService dockerMonitorService;
    @Autowired
    private  MonitorConfig        monitorConfig;
    private final List<MonitorConfig.ServerConfig> serverConfigs;

    // 通过MonitorConfig获取servers
    public CompositeMonitorService(MonitorConfig monitorConfig) {
        this.serverConfigs = monitorConfig.getServers();
    }
    // key为serverIp:serviceId
    private Map<String, ServiceStatus> lastStatusMap = new HashMap<>();

    @Override
    public ServiceStatus checkStatus(MonitorConfig.ServerConfig server, MonitorConfig.ServiceConfig service)
    {
        ServiceStatus status = new ServiceStatus();
        if ("JAR".equals(service.getType()))
        {

            ServiceStatus serviceStatus = jarMonitorService.checkStatus(server, service);
            setLastStatusMap(status, lastStatusMap, server, service ,serviceStatus);
            return serviceStatus;
        }
        else if ("DOCKER".equals(service.getType()))
        {
            ServiceStatus serviceStatus = dockerMonitorService.checkStatus(server, service);
            setLastStatusMap(status, lastStatusMap, server, service ,serviceStatus);
            return serviceStatus;
        }

        return status;
    }

    public void setLastStatusMap(ServiceStatus status,Map<String, ServiceStatus> lastStatusMap,MonitorConfig.ServerConfig server, MonitorConfig.ServiceConfig service ,ServiceStatus serviceStatus)
    {
        status.setServerIp(server.getIp());
        status.setServiceId(service.getId());
        status.setServiceName(service.getName());
        status.setType(service.getType());
        status.setRunning(serviceStatus.isRunning());
        status.setMessage("不支持的服务类型: " + service.getType());
        LocalDateTime now = LocalDateTime.now();
        status.setLastCheckTime(now);
        lastStatusMap.put(server.getIp()+":"+service.getId(), status);
    }

    @Override
    public boolean startService(MonitorConfig.ServerConfig server, MonitorConfig.ServiceConfig service)
    {
        if ("JAR".equals(service.getType()))
        {
            return jarMonitorService.startService(server, service);
        }
        else if ("DOCKER".equals(service.getType()))
        {
            return dockerMonitorService.startService(server, service);
        }
        return false;
    }

    @Override
    public boolean stopService(MonitorConfig.ServerConfig server, MonitorConfig.ServiceConfig service)
    {
        if ("JAR".equals(service.getType()))
        {
            return jarMonitorService.stopService(server, service);
        }
        else if ("DOCKER".equals(service.getType()))
        {
            return dockerMonitorService.stopService(server, service);
        }
        return false;
    }

    @Override
    public boolean restartService(MonitorConfig.ServerConfig server, MonitorConfig.ServiceConfig service)
    {
        return MonitorService.super.restartService(server, service);
    }

    @Override
    public List<ServiceStatus> getAllServiceStatus()
    {
        List<ServiceStatus> statusList = new ArrayList<>();
        for (MonitorConfig.ServerConfig server : monitorConfig.getServers())
        {
            for (MonitorConfig.ServiceConfig service : server.getServices())
            {
                statusList.add(checkStatus(server, service));
            }
        }
        return statusList;
    }

    /**
     * 获取所有服务列表，包含基本信息和状态
     */
    public List<ServiceListDTO> getServiceListWithStatus()
    {
        List<ServiceListDTO> resultList = new ArrayList<>();

        // 遍历所有服务器配置
        for (MonitorConfig.ServerConfig server : serverConfigs)
        {
            // 遍历该服务器上的所有服务
            for (MonitorConfig.ServiceConfig service : server.getServices())
            {
                ServiceListDTO dto = new ServiceListDTO();

                // 设置基本信息
                dto.setServerIp(server.getIp());
                dto.setServiceId(service.getId());
                dto.setServiceName(service.getName());
                dto.setServiceType(service.getType().toString());
                dto.setPort(service.getPort());
                dto.setAutoRestart(service.getAutoRestart());
                dto.setCheckRate(service.getCheckRate());

                // 根据服务类型设置目标名称
                if ("JAR".equals(service.getType().toString()))
                {
                    dto.setTargetName(service.getJarPath());
                }
                else if ("DOCKER".equals(service.getType().toString()))
                {
                    dto.setTargetName(service.getContainerName());
                }

                // 设置状态信息
                String statusKey = server.getIp() + ":" + service.getId();
                if (lastStatusMap != null && lastStatusMap.containsKey(statusKey))
                {
                    ServiceStatus status = lastStatusMap.get(statusKey);
                    dto.setRunning(status.isRunning());
                    ZoneId        zoneId          = ZoneId.systemDefault();
                    ZonedDateTime zonedDateTime   = status.getLastCheckTime().atZone(zoneId);
                    long          timestampMillis = zonedDateTime.toInstant().toEpochMilli();

                    LocalDateTime dateTime = Instant.ofEpochMilli(timestampMillis)
                            .atZone(zoneId)
                            .toLocalDateTime();

                    dto.setLastCheckTime(timestampMillis);
                    dto.setLastDateTime(dateTime);
                }
                else
                {
                    dto.setRunning(false);
                    dto.setLastCheckTime(null);
                }

                resultList.add(dto);
            }
        }

        return resultList;
    }
}
    